/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hxg.portmgr.core.device.dslam;

import hxg.portmgr.core.dao.DaoSource;
import hxg.portmgr.core.dao.LineProfileDAO;
import hxg.portmgr.core.device.Device;
import hxg.portmgr.core.device.DeviceType;
import hxg.portmgr.core.device.intf.Intf;
import hxg.portmgr.core.device.intf.IntfState;
import hxg.portmgr.core.device.intf.IntfType;
import hxg.portmgr.core.oper.OperType;
import hxg.portmgr.core.oper.snmp.DslamSnmpOper;
import hxg.portmgr.core.oper.snmp.Value;
import hxg.portmgr.core.oper.snmp.param.AdslParam;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author hxg
 */
public class DslamUtils {

    private static final Logger logger = Logger.getLogger(DslamUtils.class.getName());

    public enum ResultAction {

        Merge, Compress, MergeAndCompress;
    }

    public enum FileName {

        ChsName("设备自定义名称[非标准字符会被替换为_]"), Model("型号"), IP("IP地址"), ID("ID号");
        final private String chsname;

        private FileName(String chsName) {
            this.chsname = chsName;
        }

        @Override
        public String toString() {
            return chsname;
        }
    }

    public static void getDslamProfiles(Collection<Device> devs) {

        ExecutorService service = Executors.newFixedThreadPool(8);
        for (final Device dev : devs) {
            if (dev.getType() == DeviceType.DSLAM) {

                System.out.println(dev);
                service.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            DslamSnmpOper oper = (DslamSnmpOper) dev.getOper(OperType.SnmpOper);
                            File f = new File(".\\DslamUtis\\DslamLineProfiles\\[" + dev.getModel() + "][" + dev.getIp() + "][" + dev.getChsName().replace('/', '_').replace('|', '_').replace(' ', '_').replace('\\', '_') + "].txt");
                            f.getParentFile().mkdirs();
                            List<LineProfile> profs = oper.getLineProfiles();
                            try (Writer pw = new BufferedWriter(new FileWriter(f))) {
                                for (LineProfile prof : profs) {
                                    pw.append(dev.getIp()).append(',');
                                    pw.append(dev.getChsName()).append(',');
                                    pw.append(prof.getChsname()).append(',');
                                    pw.append(String.valueOf(prof.getRateModeIntValue())).append(',');
                                    pw.append(String.valueOf(prof.getValue(AdslParam.FastUp))).append(',');
                                    pw.append(String.valueOf(prof.getValue(AdslParam.FastDown))).append(',');
                                    pw.append(String.valueOf(prof.getValue(AdslParam.InterLeavedUp))).append(',');
                                    pw.append(String.valueOf(prof.getValue(AdslParam.InterLeavedDown))).append(',');
                                    pw.append(String.valueOf(prof.getUp())).append(',');
                                    pw.append(String.valueOf(prof.getDown())).append('\n');
                                }
                                pw.flush();
                            } catch (Exception e) {
                                logger.log(Level.WARNING, null, e);
                            }
                        } catch (Exception e) {
                            logger.log(Level.WARNING, null, e);
                        }
                    }
                });
            }
        }
        service.shutdown();
    }

    public static void getDslamAllIntfProfile(Collection<Device> devs) {
        ExecutorService service = Executors.newFixedThreadPool(8);
        for (final Device dev : devs) {
            if (dev.getType() == DeviceType.DSLAM) {

                System.out.println(dev);
                service.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            DslamSnmpOper oper = (DslamSnmpOper) dev.getOper(OperType.SnmpOper);
                            Intf[] infs = DaoSource.getIntfDAO().getIntfs(dev);
                            File f = new File(".\\DslamUtis\\DslamIntfLineProfile\\[" + dev.getModel() + "][" + dev.getIp() + "][" + dev.getChsName().replace('/', '_').replace('|', '_').replace(' ', '_').replace('\\', '_') + "]端口线路速率模版.txt");
                            f.getParentFile().mkdirs();
                            Map<Intf, String> mp = oper.getLineProfile(infs);
                            try (Writer pw = new BufferedWriter(new FileWriter(f))) {
                                for (Intf inf : mp.keySet()) {
                                    pw.append(dev.getIp()).append(',');
                                    pw.append(dev.getChsName()).append(',');
                                    pw.append(inf.getMarkName()).append(',');
                                    pw.append(inf.getIndex()).append(',');
                                    pw.append(mp.get(inf)).append('\n');
                                }
                                pw.flush();
                            } catch (Exception e) {
                                logger.log(Level.WARNING, null, e);
                            }
                        } catch (Exception e) {
                            logger.log(Level.WARNING, null, e);
                        }
                    }
                });
            }
        }
        service.shutdown();
    }

    public static List<Future> getDslamAllIntfLineStates(Collection<Device> devs, final EnumSet<FileName> fnset) {
        ExecutorService service = Executors.newFixedThreadPool(8);
        List<Future> furs = new ArrayList<>();
        StringBuilder headsb = new StringBuilder();
        headsb.append("IP,设备名,接口名,接口索引").append(',');
        headsb.append("接口管理状态，接口操作状态，线路模板名,定义上行,定义下行").append(',');
        headsb.append(AdslParam.CurrSnrMgnUp.chsname()).append(',');
        headsb.append(AdslParam.CurrAtnUp.chsname()).append(',');
        headsb.append(AdslParam.CurrOutputPwrUp.chsname()).append(',');
        headsb.append(AdslParam.CurrAttainableRateUp.chsname()).append(',');
        headsb.append(AdslParam.CurrSnrMgnDown.chsname()).append(',');
        headsb.append(AdslParam.CurrAtnDown.chsname()).append(',');
        headsb.append(AdslParam.CurrOutputPwrDown.chsname()).append(',');
        headsb.append(AdslParam.CurrAttainableRateDown.chsname());
        final String head = headsb.toString();
        for (final Device dev : devs) {
            furs.add(service.submit(new Callable() {
                @Override
                public Object call() throws Exception {
                    Intf[] infs = dev.getIntfs();
                    ArrayList<Intf> adslinflist = new ArrayList<>();
                    for (Intf inf : infs) {
                        if (inf.getType() == IntfType.AdslIntf) {
                            adslinflist.add(inf);
                        }
                    }
                    Intf[] adslinfs = adslinflist.toArray(new Intf[0]);
                    DslamSnmpOper oper = (DslamSnmpOper) dev.getOper(OperType.SnmpOper);
                    StringBuilder fnsb = new StringBuilder(".\\exp\\DslamUtis\\IntfInfos\\");

                    for (FileName fn : fnset) {
                        switch (fn) {
                            case Model:
                                fnsb.append('[').append(dev.getModel()).append(']');
                                break;
                            case IP:
                                fnsb.append('[').append(dev.getIp()).append(']');
                                break;
                            case ID:
                                fnsb.append('[').append(dev.getId()).append(']');
                                break;
                            case ChsName:
                                fnsb.append('[').append(dev.getChsName().replace('/', '_').replace('|', '_').replace(' ', '_').replace('\\', '_')).append(']');
                                break;
                        }
                    }
                    //String devName = dev.getChsName().replace('/', '_').replace('|', '_').replace(' ', '_').replace('\\', '_');
                    File f = new File(fnsb.toString() + ".txt");
                    f.getParentFile().mkdirs();
                    System.out.println(f);
                    try (BufferedWriter wr = new BufferedWriter(new FileWriter(f, false))) {
                        Map<Intf, IntfState[]> smp = new HashMap<>();
                        Map<Intf, String> lmp = new HashMap<>();
                        Map<Intf, Map<AdslParam, Value>> qmp = new HashMap<>();
                        List<LineProfile> profs = new ArrayList<>();
                        Map<String, LineProfile> profmp = new HashMap<>();

                        //头部结构是固定的：
                        //IP，设备名，接口索引，接口名，
                        //接口管理状态，接口操作状态，
                        //线路模板名，定义上行，协商上行，最大可达上行，上行信噪比，上行输出功率，定义下行，协商下行，最大可达下行，下行信噪比，下行输出功率，
                        //凡是批量提线路质量,都先提一次端口激活情况以及线路模板数据
                        long[] d = new long[10];
                        d[0] = System.currentTimeMillis();
                        smp.putAll(oper.getIntfState(adslinfs));
                        d[1] = System.currentTimeMillis();
                        System.out.println("取接口状态模板耗时" + (d[1] - d[0]) + "ms");
                        profs.addAll(oper.getLineProfiles());

                        for (LineProfile prof : profs) {
                            profmp.put(prof.getName(), prof);
                        }
                        d[2] = System.currentTimeMillis();
                        System.out.println("取线路模板耗时" + (d[2] - d[1]) + "ms");
                        LineProfileDAO dao = (LineProfileDAO) DaoSource.LineProfileDAO.getDataSource();
                        dao.linkLinePorfiles2Device(profs, dev.getId());
                        lmp.putAll(oper.getLineProfile(adslinfs));
                        d[3] = System.currentTimeMillis();
                        System.out.println("取速率模板模板耗时" + (d[3] - d[2]) + "ms");
                        List<Intf> inflist = new ArrayList<>();
                        for (Intf inf : smp.keySet()) {
                            if (smp.get(inf)[0] == IntfState.OperUp) {
                                inflist.add(inf);
                            }
                        }
                        //System.out.println("UP inflist length="+inflist.size());
                        Intf[] newinf = new Intf[0];
                        newinf = inflist.toArray(newinf);
                        //System.out.println("UP INTF length="+newinf.length);
                        Map<AdslParam, Value>[] mps = oper.getLineState(newinf);
                        for (int i = 0; i < newinf.length; i++) {
                            qmp.put(newinf[i], mps[i]);
                        }
                        //qmp.putAll(oper.getLineState(newinf));
                        d[4] = System.currentTimeMillis();
                        System.out.println("取线路状态耗时" + (d[4] - d[3]) + "ms");
                        wr.append(head);
                        wr.newLine();
                        for (Intf inf : adslinfs) {
                            if (inf.getType() == IntfType.AdslIntf) {
                                wr.append(dev.getIp()).append(',');
                                wr.append(dev.getChsName()).append(',');
                                wr.append(inf.toString()).append(',');
                                wr.append(inf.getIndex()).append(',');
                                if (smp.containsKey(inf)) {
                                    IntfState[] states = smp.get(inf);
                                    wr.append(states[0].toString()).append(',').append(states[1].toString()).append(',');
                                } else {
                                    wr.append(',').append(',');
                                }
                                if (lmp.containsKey(inf)) {
                                    String profname = lmp.get(inf);
                                    LineProfile prof = profmp.get(profname);
                                    if (prof != null) {
                                        wr.append(profname).append(',').append(String.valueOf(prof.getUp())).append(',').append(String.valueOf(prof.getDown())).append(',');
                                    } else {
                                        wr.append(profname).append(',').append("-1").append(',').append("-1").append(',');
                                    }
                                } else {
                                    wr.append(',').append(',');
                                }
                                if (qmp.containsKey(inf)) {
                                    Map<AdslParam, Value> parammp = qmp.get(inf);
                                    //IntfState[] states = smp.get(inf);
                                    if (parammp.containsKey(AdslParam.CurrSnrMgnUp)) {
                                        wr.append(parammp.get(AdslParam.CurrSnrMgnUp).toString()).append(',');
                                    } else {
                                        wr.append("-1").append(',');
                                    }
                                    if (parammp.containsKey(AdslParam.CurrAtnUp)) {
                                        wr.append(parammp.get(AdslParam.CurrAtnUp).toString()).append(',');
                                    } else {
                                        wr.append("-1").append(',');
                                    }
                                    if (parammp.containsKey(AdslParam.CurrOutputPwrUp)) {
                                        wr.append(parammp.get(AdslParam.CurrOutputPwrUp).toString()).append(',');
                                    } else {
                                        wr.append("-1").append(',');
                                    }
                                    if (parammp.containsKey(AdslParam.CurrAttainableRateUp)) {
                                        wr.append(parammp.get(AdslParam.CurrAttainableRateUp).toString()).append(',');
                                    } else {
                                        wr.append("-1").append(',');
                                    }
                                    if (parammp.containsKey(AdslParam.CurrSnrMgnDown)) {
                                        wr.append(parammp.get(AdslParam.CurrSnrMgnDown).toString()).append(',');
                                    } else {
                                        wr.append("-1").append(',');
                                    }
                                    if (parammp.containsKey(AdslParam.CurrAtnDown)) {
                                        wr.append(parammp.get(AdslParam.CurrAtnDown).toString()).append(',');
                                    } else {
                                        wr.append("-1").append(',');
                                    }
                                    if (parammp.containsKey(AdslParam.CurrOutputPwrDown)) {
                                        wr.append(parammp.get(AdslParam.CurrOutputPwrDown).toString()).append(',');
                                    } else {
                                        wr.append("-1").append(',');
                                    }
                                    if (parammp.containsKey(AdslParam.CurrAttainableRateDown)) {
                                        wr.append(parammp.get(AdslParam.CurrAttainableRateDown).toString());
                                    } else {
                                        wr.append("-1").append(',');
                                    }
                                    wr.newLine();
                                    //wr.append(states[0].toString()).append(',').append(states[1].toString()).append(',');
                                } else {
                                    //wr.append(',').append(',');
                                    wr.newLine();
                                }
                            } else {
                                wr.append(dev.getIp()).append(',');
                                wr.append(dev.getChsName()).append(',');
                                wr.append(inf.getMarkName()).append(',');
                                wr.append(inf.getIndex());
                                wr.newLine();
                            }
                        }
                    } catch (IOException e) {
                        logger.log(Level.WARNING, null, e);
                    }
                    return "";
                }
            }));
        }
        service.shutdown();
        return furs;
    }
}
